//test1
// #include <stdio.h>
// #include <stdlib.h>
// #include <string.h>
// #include <unistd.h>
// #include <pthread.h>
// pthread_cond_t cond;
// pthread_mutex_t mutex;
// void *r1(void *arg)
// {
//     while (1)
//     {
//         pthread_cond_wait(&cond, &mutex);
//         printf("活动\n");
//     }
// }
// void *r2(void *arg)
// {
//     while (1)
//     {
//         pthread_cond_signal(&cond);
//         sleep(1);
//     }
// }
// int main(void)
// {
//     pthread_t t1, t2;
//     pthread_cond_init(&cond, NULL);
//     pthread_mutex_init(&mutex, NULL);
//     pthread_create(&t1, NULL, r1, NULL);
//     pthread_create(&t2, NULL, r2, NULL);
//     pthread_join(t1, NULL);
//     pthread_join(t2, NULL);
//     pthread_mutex_destroy(&mutex);
//     pthread_cond_destroy(&cond);
// }



// #include <iostream>
// #include <vector>
// #include <string>
// #include <functional>
// #include <unistd.h>
// #include <pthread.h>
// using namespace std;

// // 定义一个条件变量
// pthread_cond_t cond;
// // 定义一个互斥锁
// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //当前不用，但是接口需要，所以我们需要留下来
// vector<function<void()>> funcs;
// void show()
// {
//     cout << "hello show" << endl;
// }
// void print()
// {
//     cout << "hello print" << endl;
// }
// // 定义全局退出变量
// volatile bool quit = false;
// void *waitCommand(void *args)
// {
//     pthread_detach(pthread_self());
//     while (!quit)
//     {
//         // 执行了下面的代码，证明某一种条件不就绪(现在还没有场景)，要我这个线程等待
//         // 三个线程，都会进在条件变量下进行排队
//         pthread_cond_wait(&cond, &mutex); //让对应的线程进行等待，等待被唤醒
//         for(auto &f : funcs)
//         {
//             f();
//         }
//     }
//     cout << "thread id: " << pthread_self() << " end..." << endl;
//     return nullptr;
// }

// int main()
// {
//     funcs.push_back(show);
//     funcs.push_back(print);
//     funcs.push_back([](){
//         cout << "你好世界!" << endl;
//     });
//     pthread_cond_init(&cond, nullptr);
//     pthread_t t1, t2, t3;
//     pthread_create(&t1, nullptr, waitCommand, nullptr);
//     pthread_create(&t2, nullptr, waitCommand, nullptr);
//     pthread_create(&t3, nullptr, waitCommand, nullptr);
    
//     //1.通过条件变量手动控制
//     // while(true)
//     // {
//     //     char n = 'a';
//     //     cout << "请输入你的command(n/q): ";
//     //     cin >> n;
//     //     if(n == 'n') pthread_cond_signal(&cond);
//     //     else break;
//     // }
//     //sleep(1);

//     //2.自动唤醒
//     sleep(1);
//     pthread_cond_broadcast(&cond);

//     cout << "main thread quit!" << endl;
//     pthread_cond_destroy(&cond);
//     return 0;
// }

// #include <iostream>
// #include <queue>
// #include <stdlib.h>
// #include <pthread.h>
// #define NUM 8
// class BlockQueue
// {
// private:
//     std::queue<int> q;
//     int cap;
//     pthread_mutex_t lock;
//     pthread_cond_t full;
//     pthread_cond_t empty;

// private:
//     void LockQueue()
//     {
//         pthread_mutex_lock(&lock);
//     }
//     void UnLockQueue()
//     {
//         pthread_mutex_unlock(&lock);
//     }
//     void ProductWait()
//     {
//         pthread_cond_wait(&full, &lock);
//     }
//     void ConsumeWait()
//     {
//         pthread_cond_wait(&empty, &lock);
//     }
//     void NotifyProduct()
//     {
//         pthread_cond_signal(&full);
//     }
//     void NotifyConsume()
//     {
//         pthread_cond_signal(&empty);
//     }
//     bool IsEmpty()
//     {
//         return (q.size() == 0 ? true : false);
//     }
//     bool IsFull()
//     {
//         return (q.size() == cap ? true : false);
//     }

// public:
//     BlockQueue(int _cap = NUM) : cap(_cap)
//     {
//         pthread_mutex_init(&lock, NULL);
//         pthread_cond_init(&full, NULL);
//         pthread_cond_init(&empty, NULL);
//     }
//     void PushData(const int &data)
//     {
//         LockQueue();
//         while (IsFull())
//         {
//             NotifyConsume();
//             std::cout << "queue full, notify consume data, product stop." << std::endl;
//             ProductWait();
//         }
//         q.push(data);
//         // NotifyConsume();
//         UnLockQueue();
//     }
//     void PopData(int &data)
//     {
//         LockQueue();
//         while (IsEmpty())
//         {
//             NotifyProduct();
//             std::cout << "queue empty, notify product data, consume stop." << std::endl;
//             ConsumeWait();
//         }
//         data = q.front();
//         q.pop();
//         // NotifyProduct();
//         UnLockQueue();
//     }
//     ~BlockQueue()
//     {
//         pthread_mutex_destroy(&lock);
//         pthread_cond_destroy(&full);
//         pthread_cond_destroy(&empty);
//     }
// };
// void *consumer(void *arg)
// {
//     BlockQueue *bqp = (BlockQueue *)arg;
//     int data;
//     for (;;)
//     {
//         bqp->PopData(data);
//         std::cout << "Consume data done : " << data << std::endl;
//     }
// }
// // more faster
// void *producter(void *arg)
// {
//     BlockQueue *bqp = (BlockQueue *)arg;
//     srand((unsigned long)time(NULL));
//     for (;;)
//     {
//         int data = rand() % 1024;
//         bqp->PushData(data);
//         std::cout << "Prodoct data done: " << data << std::endl;
//         // sleep(1);
//     }
// }
// int main()
// {
//     BlockQueue bq;
//     pthread_t c, p;
//     pthread_create(&c, NULL, consumer, (void *)&bq);
//     pthread_create(&p, NULL, producter, (void *)&bq);
//     pthread_join(c, NULL);
//     pthread_join(p, NULL);
//     return 0;
// }

#include <iostream>
#include <vector>
#include <stdlib.h>
#include <semaphore.h>
#include <unistd.h>
#include <pthread.h>
#define NUM 16
class RingQueue
{
private:
    std::vector<int> q;
    int cap;
    sem_t data_sem;
    sem_t space_sem;
    int consume_step;
    int product_step;

public:
    RingQueue(int _cap = NUM) : q(_cap), cap(_cap)
    {
        sem_init(&data_sem, 0, 0);
        sem_init(&space_sem, 0, cap);
        consume_step = 0;
        product_step = 0;
    }
    void PutData(const int &data)
    {
        sem_wait(&space_sem); // P
        q[consume_step] = data;
        consume_step++;
        consume_step %= cap;
        sem_post(&data_sem); // V
    }
    void GetData(int &data)
    {
        sem_wait(&data_sem);
        data = q[product_step];
        product_step++;
        product_step %= cap;
        sem_post(&space_sem);
    }
    ~RingQueue()
    {
        sem_destroy(&data_sem);
        sem_destroy(&space_sem);
    }
};
void *consumer(void *arg)
{
    RingQueue *rqp = (RingQueue *)arg;
    int data;
    for (;;)
    {
        rqp->GetData(data);
        std::cout << "Consume data done : " << data << std::endl;
        sleep(1);
    }
}
// more faster
void *producter(void *arg)
{
    RingQueue *rqp = (RingQueue *)arg;
    srand((unsigned long)time(NULL));
    for (;;)
    {
        int data = rand() % 1024;
        rqp->PutData(data);
        std::cout << "Prodoct data done: " << data << std::endl;
        // sleep(1);
    }
}
int main()
{
    RingQueue rq;
    pthread_t c, p;
    pthread_create(&c, NULL, consumer, (void *)&rq);
    pthread_create(&p, NULL, producter, (void *)&rq);
    pthread_join(c, NULL);
    pthread_join(p, NULL);
}